﻿using System;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Configuration;


namespace teadmillSimulator {
    public class Server {
        private const int waitForData = 0;
        private const int sendTrainingData = 1;
        private int state;
        private int gear = -1;


        //static TcpListener listener;
        private TcpListener Mserver;
        private const int LIMIT = 5; //5 concurrent clients

        private const Int32 port = 2055;
        //private IPAddress localAddr = IPAddress.Parse("172.30.4.52");
        private IPAddress localAddr = IPAddress.Parse("127.0.0.1");
        //private Thread t;
        private string name;


        private DataGenerator dataGenerator = new DataGenerator();
        private Thread myThread;
        private StreamReader sr;
        private StreamWriter sw;

        public Server() {
            Console.WriteLine("Server init...");
            state = waitForData;
        }

        public void CreateConnection() {
            Mserver = new TcpListener(localAddr, port);
            Console.WriteLine("Server is Started");
            Mserver.Start();

            for (int i = 0; i < LIMIT; i++) {
                Thread t = new Thread(Service);
                t.Start();
            }

            myThread = new Thread(generatorThread);
            myThread.Start();
            myThread.Suspend();
            myThread.IsBackground = true;
        }


        public void recieve() {
            //myThread = new Thread(thread_func);
        }


        public void Service() {
            while (true) {
                Socket soc = Mserver.AcceptSocket();
                Console.WriteLine("Client has logged on");
                //myThread.Suspend();

                //soc.SetSocketOption(SocketOptionLevel.Socket,
                //        SocketOptionName.ReceiveTimeout,10000);

                try {
                    Stream s = new NetworkStream(soc);
                    sr = new StreamReader(s);
                    sw = new StreamWriter(s);
                    sw.AutoFlush = true; // enable automatic flushing
                    //sw.WriteLine("server is Ready");
                    while (true) {
                        name = sr.ReadLine();

                        switch (state) {
                            case waitForData:
                                Console.WriteLine("State: waitForData ");
                                if (name.Equals("[")) {
                                    state = sendTrainingData;
                                    myThread.Resume();
                                } else if (name.Equals("]")) {
                                    state = waitForData;
                                    myThread.Suspend();
                                } else {
                                    try {
                                        gear = Convert.ToInt32(name);
                                    } catch (FormatException e) {
                                        Console.WriteLine("not an NUMBER: " + e);

                                        throw;
                                    }
                                    Console.WriteLine("Gear: " + gear);
                                }

                                break;
                            case sendTrainingData:
                                Console.WriteLine("State: sendTrainingData ");
                                if (name.Equals("[")) {
                                    state = sendTrainingData;
                                    myThread.Resume();
                                } else if (name.Equals("]")) {
                                    state = waitForData;
                                    myThread.Suspend();
                                } else {
                                    Console.WriteLine("Gear: " + gear);
                                }
                                break;
                            default:
                                Console.WriteLine("SOMETHING WRONG WITH PROTOCOL");
                                myThread.Suspend();
                                break;
                        }

                        sw.WriteLine("");
                    }
                    //}
                    s.Close();
                } catch (Exception e) {
                    soc.Close();
                }
                Console.WriteLine("Clien has Logged Off");
                myThread.Suspend();
                state = waitForData;
            }
        }


        private void generatorThread() {
            while (true) {
                String str = dataGenerator.generateTeatmillData();
                try {
                    sw.WriteLine(str);
                } catch (Exception e) {
                    Console.WriteLine(e.StackTrace);
                    Console.WriteLine("dataGenerator Failed");
                }
                Thread.Sleep(500);
            }
        }
    }
}